#pragma once
#include <pthread.h>
#include <signal.h>
#include "Socket.h"
#include "Protocol.h"
#include "ThreadPool.hpp"

class Task
{
public:
    Task(int sockfd)
        : _sockfd(sockfd)
    {
    }

    void operator()()
    {
        LogMessage(TEST, "Task: sockfd:%d tid:%ul", _sockfd, pthread_self());
        EndPoint *ep = new EndPoint(_sockfd);
        if (ep->GetReq())
        {
            // LogMessage(TEST, "get a complete request message!");
            ep->AnalyseReq();
            ep->BuildResp();
            ep->DebugPrint();
            ep->SendResp();
        }
        delete ep;
        close(_sockfd);
    }

private:
    int _sockfd;
};

class HttpServer
{
public:
    static HttpServer* GetInstance(uint16_t port)
    {
        if(s_inst == nullptr)
        {
            pthread_mutex_lock(&_mtx);
            if(s_inst == nullptr)
            {
                s_inst = new HttpServer(port);
            }
            pthread_mutex_unlock(&_mtx);
        }
        return s_inst;
    }

    void Run()
    {
        while (!_quit)
        {
            string client_ip;
            uint16_t client_port;
            int sockfd = _listensock.Accept(&client_ip, &client_port);
            if (sockfd == -1)
                continue;
            LogMessage(TEST, "get a new link! fd:%d ip:%s port:%hu", sockfd, client_ip.c_str(), client_port);
            // 构建Task交给线程池处理
            _tp.PushTask(Task(sockfd));
        }
    }

private:
    Socket _listensock;
    uint16_t _port;
    bool _quit = false;
    ThreadPool<Task> _tp;
    static HttpServer *s_inst; //把http服务器设计成单例
    static pthread_mutex_t _mtx;

    HttpServer(uint16_t port)
        : _port(port)
    {
        _listensock.SetPortReuse();
        _listensock.Bind(_port);
        _listensock.Listen();
        // 解决broken pipe写入出错
        signal(SIGPIPE, SIG_IGN);
        // 运行线程池
        _tp.Run();
    }

    HttpServer(const HttpServer&) = delete;
    HttpServer& operator=(const HttpServer&) = delete;
};

HttpServer *HttpServer::s_inst = nullptr;
pthread_mutex_t HttpServer::_mtx = PTHREAD_MUTEX_INITIALIZER;